/*
 * Copyright (C) 2009 Kristopher T Babic
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, see <http://www.gnu.org/licenses>.
 */

package edu.idp.client.anim.sequence;

import edu.idp.client.Stopwatch;

import java.awt.*;
import java.io.Serializable;

/**
 *
 * @author Kristopher T Babic
 */
public abstract class Sequence extends Object implements Cloneable, Serializable {

    static final long serialVersionUID = -4632574860224502092L;

    private static long infiniteCycle = -1;

    private Point lastPaintLocation = new Point(0, 0);
    private Stopwatch cellAdvanceTimer = null;
    private long cellAdvanceInterval = 0,
            currentCycle = 0,
            cyclesPerAnimation = 0;
    protected transient Image currentImage, lastImagePainted;

    protected transient Component myComp;

    public Sequence() {
        cyclesPerAnimation = infiniteCycle;
    }

    public abstract String toString();

    public abstract Image getFirstImage();

    public abstract Image getCurrentImage();

    public abstract Image getNextImage();

    public abstract boolean isAtLastImage();

    protected abstract void initImages();

    public Component getComponent() {
        return myComp;
    }

    public void setComponent(Component c) {
        this.myComp = c;
        cellAdvanceTimer = new Stopwatch();
    }

    public void removeComponentOnly() {
        this.myComp = null;
    }

    public void setComponentOnly(Component c) {
        this.myComp = c;
    }

    public void start() {
        if (cellAdvanceTimer == null)
            cellAdvanceTimer = new Stopwatch();
        cellAdvanceTimer.start();
    }

    public Image getLastImage() {
        return lastImagePainted;
    }

    public Point getLastLocation() {
        return lastPaintLocation;
    }

    public long getCurrentCycle() {
        return currentCycle;
    }

    public void setCurrentCycle(long c) {
        currentCycle = c;
    }

    public long getCyclesPerAnimation() {
        return currentCycle;
    }

    public void setCyclesPerAnimation(long cyclesPerAnimation) {
        this.cyclesPerAnimation = cyclesPerAnimation;
    }

    public void setAdvanceInterval(long interval) {
        cellAdvanceInterval = interval;
    }

    public boolean needsRepainting(Point point) {
        return (lastPaintLocation.x != point.x ||
                lastPaintLocation.y != point.y ||
                lastImagePainted != currentImage);
    }

    public boolean timeToAdvanceCell() {
        return
                cellAdvanceTimer.elapsedTime() > cellAdvanceInterval;
    }

    public boolean animationOver() {
        return (cyclesPerAnimation != infiniteCycle) &&
                (currentCycle >= cyclesPerAnimation);
    }

    public void advance() {
        if (isAtLastImage())
            advanceCycle();

        currentImage = getNextImage();
        cellAdvanceTimer.reset();
    }

    protected void advanceCycle() {
        ++currentCycle;
    }

    public Sequence copy() {
        try {
            return (Sequence) this.clone();
        }
        catch (Exception e) {
            return null;
        }
    }

}
